Auto Resize Multiline Editable Text Field in Jquery - javascript

I'm looking auto-resize the font for each new line of equal width for a multi-line editable text field. Please check the url below:
http://api.pstr.co/html/template/003_script
Right now the font-size is like that
and I want to be like that:
The jquery code for this plugin is this:
function getBaseFontSize(){
var baseFontSize = Math.round(0.15*Math.min($(window).width(), $(window).height()));
return baseFontSize;
}
function editModeSetup(){
var contentBlock = $(".content");
var container = $(".block");
var scalableText = $(".scalable");
$('[contenteditable]').each(function (index) {
var $this = $(this);
$this
.on("keydown", function(){
clearTimeout($this.timeout);
fitTextMultiline(scalableText,contentBlock,container);
//if (!$this.hasClass("edited")) $(this).addClass("edited");
}).on("focus", function () {
//if (!$this.hasClass("edited")){
$this.selectText();
//}
// Work around Chrome's little problem
$this.mouseup(function() {
// Prevent further mouseup intervention
$this.unbind("mouseup");
return false;
});
}).on("keyup", function () {
$this.timeout = setTimeout(function(){ fitTextMultiline(scalableText,contentBlock,container); }, 400);
});
//$(".content").css("font-size", getBaseFontSize());
$("html").css("font-size", getBaseFontSize());
});
fitTextMultiline(scalableText,contentBlock,container);
$(window).resize(function() {
fitTextMultiline(scalableText,contentBlock,container);
});
var myWidth = window.innerWidth;
var myHeight = window.innerHeight;
ga('send',
'event',
'Viewport',
'Size',
myWidth+'x'+myHeight,
{'nonInteraction': 1});
}
function fitTextMultiline(scalableText, contentBlock, container) {
// startvwith small type and push the size up? to make sure more fits on one line...
var maxHeight = container.height();
var maxWidth = container.width();
//console.log(".\n")
//console.log(scalableText.text())
var fontSize = 7*getBaseFontSize(); // 20;
var fontUnits = "px"; // "vmin";
do {
scalableText.css('font-size', fontSize+fontUnits);
contentHeight = contentBlock.height();
contentWidth = contentBlock.width();
//console.log("--- " + fontSize +" ---")
//console.log(contentHeight + " ? " + maxHeight)
//console.log(contentWidth + " ? " + maxWidth)
fontSize = Math.round(fontSize - fontSize*0.1);
} while ((contentHeight > maxHeight || contentWidth > maxWidth ) && fontSize > 10);
//+ fontSize/2
alignPrices();
doubleLineAssignClasses();
return this;
}
// code that returns text from edit mode
function getPosterText() {
/*
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-61477423-5', 'auto');
ga('send', 'pageview');
*/
ga('send', 'event', 'Button', 'Save', document.title);
var list = $('[contenteditable]').map(function () {
//console.log($(this).text());
//console.log($(this).val());
//console.log(_jsonEscape($(this).val()));
//return $(this).text();
return $(this).html();
}).toArray();
return _jsonEscape(JSON.stringify(list));
}
// code that sets text in edit mode
function setPosterText(text) {
/*
var list;
console.log(text)
try {
list = JSON.parse(text)
}
catch (e) {
console.log('Cannot parse given texts json.');
list = [];
}
*/
//if (list.length > 0)
/*
$('[contenteditable]').each(function (index) {
//$(this).text(list[index] || "");
$(this).addClass("userText")
});
*/
//var contentBlock = $(".content");
//var container = $(".block");
//var scalableText = $(".scalable");
//fitTextMultiline(scalableText,contentBlock,container);
}
function _jsonEscape(str) {
//str = str.replace(/&/g,"&").replace(/£/g,"£");
//str.replace(/£/g,"£");
return str.replace(/\\n/g, "\\\\n").replace(/\\r/g, "\\\\r").replace(/\\t/g, "\\\\t");
}
function editableListFix(){
$('ul').on('keyup keydown', function() {
var $this = $(this);
if (! $this.html()) {
var $li = $('<li></li>');
var sel = window.getSelection();
var range = sel.getRangeAt(0);
range.collapse(false);
range.insertNode($li.get(0));
range = range.cloneRange();
range.selectNodeContents($li.get(0));
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
} else {
//are there any tags that AREN'T LIs?
//this should only occur on a paste
var $nonLI = $this.find(':not(li, br)');
if ($nonLI.length) {
$this.contents().replaceWith(function() {
//we create a fake div, add the text, then get the html in order to strip out html code. we then clean up a bit by replacing nbsp's with real spaces
return '<li>' + $('<div />').text($(this).text()).html().replace(/ /g, ' ') + '</li>';
});
//we could make this better by putting the caret at the end of the last LI, or something similar
}
}
});
}
function alignPricesFix(){
alignPrices()
$('[contenteditable]').each(function (index) {
var $this = $(this);
$this
.on("keyup keydown", function(){
alignPrices();
});
});
}
function alignPrices(){
var positions = [];
var heights = [];
$( ".items>li" ).each(function( index ) {
positions.push( $( this ).position().top );
heights.push( $( this ).height() );
});
$( ".prices>li" ).each(function( index ) {
//$( this ).css("top", positions[index]);
$( this ).css("height", heights[index]);
});
ulPrices = $( "ul.prices" );
if (ulPrices) ulPrices.css("height", $( "ul.items" ).height());
}
function doubleLineAssignClasses(){
$( ".double-line>li" ).each(function( index ) {
$( this ).removeClass('item-header');
$( this ).removeClass('item-description');
//if (!$( this ).hasClass('item-header') && !$( this ).hasClass('item-description') ){
if (index % 2 != 1) $( this ).addClass('item-header')
else $( this ).addClass('item-description') ;
//console.log(index);
});
}

check this website for the jQuery/javascript solution https://css-tricks.com/forums/topic/is-it-possible-to-adapt-font-size-to-div-width/
I quote it here also:
"Hey, this isn’t going to be achievable with CSS alone, but you could certainly do this using jquery/javascript. For example you could enclose each word in a span, measure the width of that span, divide the width of the parent div by the span width, then multiply the font-size of the span text by that number.
i.e: (div width/span width) * span font-size"

Related

jQuery - Multiple expanding galleries in tabs

I'm trying to get this code "Reveal gallery by Roko C. Buljan" - http://jsbin.com/zariku/9/edit?html,css,js,output - to work in multiple tabs here:
http://codepen.io/anon/pen/QjyMwg
JS:
var $prvw = $('#preview'),
$gall = $('.gooGallery'),
$li = $gall.find("li"),
$img = $prvw.find("img"),
$alt1 = $prvw.find("h2"),
$alt2 = $prvw.find("p"),
$full = $("<li />", {"class":"full", html:$prvw});
$li.attr("data-src", function(i, v){
$(this).css({backgroundImage: "url("+v+")"});
}).on("click", function( evt ){
var $el = $(this),
d = $el.data(),
$clone = $full.clone();
$el.toggleClass("active").siblings().removeClass("active");
$prvw.hide();
$full.after($clone);
$clone.find(">div").slideUp(function(){
$clone.remove();
});
if(!$el.hasClass("active")) return;
$img.attr("src", d.src);
$alt1.text(d.alt);
$alt2.text(d.title);
$li.filter(function(i, el){
return el.getBoundingClientRect().top < evt.clientY;
}).last().after($full);
$prvw.slideDown();
});
$(window).on("resize", function(){
$full.remove();
$li.removeClass("active");
});
2nd tab is working fine, but, when I'll try to open the first one the div isn't shown on the right position.
Can anyone please help me with a hint?
You're trying to use the same preview div for both gallerys. Try having 2 previews. Quickest way I could think would be do to something like this (be warned, this is kinda ugly):
var i = 1;
$('.gooGallery').each(function() {
var $gall = $(this);
var $prvw = $('#preview' + i); i = i+1;
var $li = $gall.find("li")
var $img = $prvw.find("img")
var $alt1 = $prvw.find("h2")
var $alt2 = $prvw.find("p")
var $full = $("<li />", {
"class" : "full",
html : $prvw
});
$li.attr("data-src", function (i, v) {
$(this).css({
backgroundImage : "url(" + v + ")"
});
}).on("click", function (evt) {
var $el = $(this),
d = $el.data(),
$clone = $full.clone(true);
$el.toggleClass("active").siblings().removeClass("active");
$prvw.hide();
$full.after($clone);
$clone.find(">div").slideUp(function () {
$clone.remove();
});
if (!$el.hasClass("active"))
return;
$img.attr("src", d.src);
$alt1.text(d.alt);
$alt2.text(d.title);
$li.filter(function (i, el) {
return el.getBoundingClientRect().top < evt.clientY;
}).last().after($full);
$prvw.slideDown();
});
$(window).on("resize", function () {
$full.remove();
$li.removeClass("active");
});
});
And then modify the preview div
<div id="preview1" class='preview'>
<img src="//placehold.it/300x180/369">
<div><h2></h2><p></p></div>
</div>
<div id="preview2" class='preview'>
<img src="//placehold.it/300x180/369">
<div><h2></h2><p></p></div>
</div>
Thought it looked weird so threw in the necessary css changes:
.preview{
display:none;
}
.preview > *{
float:left;
margin:3%;
}
.preview img{
max-width:100%;
}

Html selection all it works. but it throws error when select with `space`

I am doing a selection, and on highlight i adding a space. when user select the same span, i console the message.
all working fine. but when i select a existing node element (strong) with space, i am getting an error as The Range has partially selected a non-Text node.
how to solve this?
here is my code :
var currentTarget = null;
function selHTML() {
var nNd = document.createElement("span");
var w = getSelection().getRangeAt(0);
var text = window.getSelection().toString();
currentTarget = $(w.startContainer).parent();
//console.log(selection.anchorNode.baseURI);//nextElementSibling/anchorNode
if(!$(w.startContainer).parent().prop('class')) {
if($.trim(text).length < 5 ) {
console.log("Your selection is too short..!");
return;
}
try {
w.surroundContents(nNd);
currentTarget.find('span.highlight').contents().unwrap();
$(nNd).addClass('highlight');
} catch (ex) {
console.log("The Range has partially selected a non-Text node.")
}
} else {
console.log("already selected");
}
}
$("#addText").on('click', function(event) {
event.preventDefault();
$(selHTML());
});
$("button").click(function(){
$(selHTML());
});
$("#clearSpan").click(function(){
console.log($(currentTarget))
});
$("div.content").mouseup(function(event) {
var range = window.getSelection().getRangeAt(0);
if (!range.collapsed) {
var bounds = range.getBoundingClientRect();
var x = bounds.left + ((bounds.right - bounds.left - $(".savetooltipAll").outerWidth()) / 2);
var y = bounds.top - $(".savetooltipAll").outerHeight() + $(window).scrollTop();
$(".savetooltipAll").css("top", (y+(bounds.top*3)) + 'px');
$(".savetooltipAll").css("left",x + 'px');
$(".savetooltipAll").show();
} else {
$(".savetooltipAll").hide();
}
});
Demo
Highlight selected text on a page when spanning multiple non text nodes:
Highlight selected text on a page when spanning multiple non text nodes

Change .css() after the .click()

I wrote me a slider. The slider works perfect, but the absolute last thing won't work. I cant't reset my width. I tried to call a function via the deferred.done function from jQuery API. At the end I put something like that dfd.resolve( "and" );. This works only one time. How can I change $("#first" ).css("width", t_first); width again?
My JS code:
$("#zero-img" ).click(function() {
$(function () {
var width_slider = ($( "#slider" ).width()) ;
var width_first = $( "#first" ).width() ;
var width_first_img = $( "#first-img" ).width() ;
var width_first_img_container = $( "#first-img-container" ).width() ;
var width_first_tex = $( "#first-img-text" ).width() ;
var width_gap = width_slider - width_first - 300;
var width_img = $( "#first-img-container" ).width() ;
var t_first = width_first + width_gap;
$("#first" ).css("width", t_first); //THIS I WANT TO CHANGE AGAIN AFTER FINISHED THE CLICK ACTION
$("#next-img" ).animate({ width:0 }, "slow" );
$("#first-img" ).animate({ left: width_first}, "slow", function(){
if ($("#next-img-container").attr("src").length > 0) {
var path_on_hold = $("#next-img-container").attr("src");
$("#on-hold-img-container").attr("src", path_on_hold);
var value_on_hold = $("#next-img-container").attr("value");
$("#on-hold-img-container").attr("value", value_on_hold);
var path_next = $("#first-img-container").attr("src");
$("#next-img-container").attr("src", path_next);
var value_next = $("#first-img-container").attr("value");
$("#next-img-container").attr("value", value_next);
}
$(this).css('left', (-1)* width_first);
var first_img = $("#zero-img-container").attr("src");
$("#first-img-container").attr("src",first_img);
var value_first = $("#zero-img-container").attr("value");
$("#first-img-container").attr("value", value_first);
} );
$("#zero-img" ).animate({ left:-150 }, "slow", function() {
if ($("#zero-on-hold-img-container").attr("src").length > 0) {
var path_zero = $("#zero-on-hold-img-container").attr("src");
$("#zero-img-container").attr("src", path_zero);
var value_zero = $("#zero-on-hold-img-container").attr("value");
$("#zero-img-container").attr("value", value_zero);
var pics = <?php echo json_encode($pics)?>;
var number = parseInt($("#zero-on-hold-img-container").attr("value"));
if (pics.hasOwnProperty(number-1) === true ) {
var company_id = pics[number-1].company_id;
var filename = pics[number-1].filename;
var temp = path + pics[number-1].company_id + "/" + pics[number-1].filename;
$("#zero-on-hold-img-container").attr("src", temp);
$("#zero-on-hold-img-container").attr("value", number-1);
$("#zero-on-hold-img-container").attr("value", number-1);
} else {
$("#zero-on-hold-img-container").attr("src", "");
$("#zero-on-hold-img-container").attr("value", "");
}
} else {
if ($("#zero-img-container").attr("src").length > 0) {
$("#zero-img-container").attr("src", "");
$("#zero-img-container").attr("value", "");
}
}
});
$("#zero-img").animate({ left: 0 }, "slow");
$("#next-img" ).animate({ width:150 }, "slow" );
$("#first-img").animate({ left: 15 }, "slow");
/*$("#first" ).css("width", auto);*/
});
});
The reason it only works once is because width_slider is set initially to your correct width, but then you are changing the width to auto, thus width_slider will never again be the initial width.
<!-- put the initial width of slider in data-init-width -->
<div id="slider" data-init-width="960"> ... </div>
Script:
$('#zero-img').click(function() {
var initialWidth = Number($('#slider').attr('data-init-width'));
if ( $('#slider').width() != initialWidth ){
$('#slider').css({
width: initialWidth + 'px'
});
}
var width_slider = $('#slider').width();
// do the other stuff
});
Then use the mouseup method
$('#zero-img').mouseup(function(){
// change the width to the after click width
});

JQuery Resizable - Update element absolute position while resizing

I have many divs distributed in rows and columns, (generated using jQuery). Each one of these divs is re-sizable, using JQuery UI Resizable. In order to define the requirements, all divs must use absolute positioning. So, when I re-size any of these divs, the script should update the top attribute of all divs below this, (located in the same column and one row after the current resizing div).
This is the code I have now:
updatePositions: function() {
var update = 0;
$(".element").resizable({
handles: 's',
start: function(event, ui) {
event.stopPropagation();
var el = $(this);
var el_row = parseInt(el.attr("row"));
var el_rel = parseInt(el.attr("rel"));
var el_col = parseInt(el.attr("col"));
update = $(".element").filter(function() {
return(
$(this).attr("row") > el_row &&
$(this).attr("col") == el_col &&
$(this).attr("rel") != el_rel
);
});
},
resize: function(event, ui) {
update.each(function(event){
var top = $(this).position().top + $(this).height() + 20;
$(this).css("top", top )
});
}
})
}
And here is an example: JSFiddle
As you can see, all the divs are found just right and I can update the top position. But for some reason it's getting crazy when resizing! It seems like I'm doing the update as many times as found tiles on each selected div.
finally I solved this problem. JSFiddle
this is the js code:
function CacheType(){
corrtop = 0;
rel = 0;
}
$.extend({
updatePositions: function() {
var update = 0;
var arr = new Array();
$(".element").resizable({
handles: 's',
start: function(event, ui) {
event.stopPropagation();
var el = $(this);
var el_row = parseInt(el.attr("row"));
var el_rel = parseInt(el.attr("rel"));
var el_col = parseInt(el.attr("col"));
var ex = el.position().top;
var ey = el.height();
update = $(".element").filter(function() {
if(
$(this).attr("row") > el_row &&
$(this).attr("col") == el_col &&
$(this).attr("rel") != el_rel
){
var tmp = new CacheType();
tmp.corrtop = $(this).position().top - ex - ey;
tmp.rel = $(this).attr('rel');
arr.push(tmp);
return true;
}else{
return false;
}
});
},
resize: function(event, ui) {
var x = $(this).height() + $(this).position().top;
update.each(function(event){
for(var i=0;i<arr.length; i++){
var tmp = arr[i];
var rel = $(this).attr('rel');
if(rel == tmp.rel)
$(this).css("top", x + tmp.corrtop);
}
});
}
})
}
});
$(document).ready(function(){
$.updatePositions();
});

Can't append to second container

I have the following script:
(function($) {
$.fn.easyPaginate = function(options){
var defaults = {
step: 4,
delay: 100,
numeric: true,
nextprev: true,
controls: 'pagination',
current: 'current'
};
var options = $.extend(defaults, options);
var step = options.step;
var lower, upper;
var children = $(this).children();
var count = children.length;
var obj, next, prev;
var page = 1;
var timeout;
var clicked = false;
function show(){
clearTimeout(timeout);
lower = ((page-1) * step);
upper = lower+step;
$(children).each(function(i){
var child = $(this);
child.hide();
if(i>=lower && i<upper){ setTimeout(function(){ child.fadeIn('fast') }, ( i-( Math.floor(i/step) * step) )*options.delay ); }
if(options.nextprev){
if(upper >= count) { next.addClass('stop'); } else { next.removeClass('stop'); };
if(lower >= 1) { prev.removeClass('stop'); } else { prev.addClass('stop'); };
};
});
$('li','#'+ options.controls).removeClass(options.current);
$('li[data-index="'+page+'"]','#'+ options.controls).addClass(options.current);
if(options.auto){
if(options.clickstop && clicked){}else{ timeout = setTimeout(auto,options.pause); };
};
};
function auto(){
if(upper <= count){ page++; show(); }
else { page--; show(); }
};
this.each(function(){
obj = this;
if(count>step){
var pages = Math.floor(count/step);
if((count/step) > pages) pages++;
var ol = $('<ol id="'+ options.controls +'" class="pagin"></ol>').insertAfter(obj);
if(options.nextprev){
prev = $('<li class="prev">prev</li>')
.appendTo(ol)
.bind('click', function() {
//check to see if there are any more pages in the negative direction
if (page > 1) {
clicked = true;
page--;
show();
}
});
}
if(options.numeric){
for(var i=1;i<=pages;i++){
$('<li data-index="'+ i +'">'+ i +'</li>')
.appendTo(ol)
.click(function(){
clicked = true;
page = $(this).attr('data-index');
show();
});
};
};
if(options.nextprev){
next = $('<li class="next">next</li>')
.appendTo(ol)
.bind('click', function() {
//check to see if there are any pages in the positive direction
if (page < (count / 4)) {
clicked = true;
page++;
show();
}
});
}
show();
};
});
};
})(jQuery);
jQuery(function($){
$('ul.news').easyPaginate({step:4});
});
which is a carousel-like plugin that produces this html structure for the navigation:
<ol id="pagination" class="pagin"><li class="prev">prev</li><li data-index="1" class="">1</li><li data-index="2" class="">2</li><li data-index="3" class="current">3</li><li class="next stop">next</li></ol>
And all I want is to enclose this list in a div. Seems simple, but appendTo doesn't want to cooperate with me, or I'm doing something wrong (I'd appreciate if you would help me understand what that is..)
So I'm modifying as such:
var ol = $('<ol id="'+ options.controls +'" class="pagin"></ol>');
var tiv = $('<div id="lala"></div>');
ol.appendTo('#lala');
tiv.insertAfter(obj);
I know how to chain, but I'm in "debugging" mode trying to understand why I don't get the result I imagine I would get:
<div id="lala>
<ol id="pagination><li>...... </li></ol>
</div>
I tried putting some console.log's to see the status of my variables but couldn't find something useful.. I guess there's something with DOM insertion I don't get.
You're appending the <ol> element to #lala before adding the latter to the document. There's nothing wrong with this, but since you're using an id selector, and the target element is not part of the document yet, the selector will not match anything.
To fix this, you can write:
var ol = $('<ol id="'+ options.controls +'" class="pagin"></ol>');
var tiv = $('<div id="lala"></div>');
ol.appendTo(tiv);
tiv.insertAfter(obj);
Or:
var ol = $('<ol id="'+ options.controls +'" class="pagin"></ol>');
var tiv = $('<div id="lala"></div>');
tiv.insertAfter(obj);
ol.appendTo('#lala');

Categories

Resources