Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 8 of 8
  1. #1
    New to the CF scene
    Join Date
    Aug 2016
    Posts
    6
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Same control type but different events just does not work

    Hi All,

    I started this last weekend and I thought I would pick it up again.

    On a form I have two of the same types of controls "Input", I've added an event "change" and I iterate though the dom to find them e.g querySelectorAll(".file-field"), but when I pause using lets say chrome, and select a file for the first input it ALWAYS want to look at the files from the second Input and I just cannot figure out how to go about fixing it.

    I can post HTML and JS if that help, if I have on a single type of the control on a form it works fine.

    I reply hope somebody can help.

  2. #2
    Administrator VIPStephan's Avatar
    Join Date
    Jan 2006
    Location
    Halle (Saale), Germany
    Posts
    10,876
    Thanks
    6
    Thanked 1,299 Times in 1,269 Posts
    Yes, please post your code. After all, this site is called CodingForums, not PsychicForums.

  3. #3
    New to the CF scene
    Join Date
    Aug 2016
    Posts
    6
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Actually I did post it last week on the forum but got no replies so I though I would try a different approach.

    multiple-calls-not-calling-individual-element.html

  4. #4
    Senior Coder deathshadow's Avatar
    Join Date
    Feb 2016
    Location
    Keene, NH
    Posts
    2,374
    Thanks
    2
    Thanked 338 Times in 328 Posts
    Well first, STOP using the blasted style attribute to slop the same values in over and over and over defeating the entire reason CSS is separate from HTML. If nothing else you're just making it harder to diagnose and work with.

    NEXT, stop using div and span to do LABEL's job.

    NEXT inputs don't have title attributes.

    NEXT stop using classes for nothing, you should have a parent FIELDSET you can hook these off of for the style. (of course with all that inline style why in blazes bother with classes?)

    Of course if it's 'hidden' what good is it...

    Yeah, once I start deleting the cruft to see what you are doing, are you INTENTIONALLY trying to make the form inaccessible/harder to use? That seems to be the entire point of your scripting and all these pointless extra elements.


    That and type="file" can't be copied from one to another. It's value doesn't work that way. ALSO beware that in IE, onchange doesn't fire until the element loses focus -- that can wreak havoc with trying to do stuff like this in JavaScript.

    You've got a LOT of problems that need to be cleaned up before throwing JavaScript at this... made even WORSE by a lot of that JavaScript seeming to be there to do CSS' job! See pretty much all your use of Element.style in regards to mouseover/mouseout. This isn't 1997, and even when it was that's wrong.
    I would rather have questions that can't be answered, than answers that can't be questioned.
    http://www.cutcodedown.com

  5. #5
    New to the CF scene
    Join Date
    Aug 2016
    Posts
    6
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Actually how rude can somebody be, I do know about CSS styles thank you very much, I wanted to get it working before I separated out the CSS from the main content, now it is based on Materialize CSS so if you want to have a go about labels and the stuff I would contact them, I'm sure they would be glad for the advice.

    if you did really take a look you will find that the default file selector in any browser is awful, so one of the ways around this is to hide it with opacity e.g 0, but the default behaviour still will works, so the input text field will live above the input file, with a little bit of z-indexing

    Now the idea behind the Mouse over and out is that when I user moves there mouse over to the far right hand side, an icon will appear press this and the text in the input text will disappear.

    The classes are there so you can latch on to the correct control type, this is how Bootstrap and Materialize CSS do it in their "API" if you will, if you have multiple controls or control blocks if you will and you want JQuery or javascript to pick them up classes is the only way you can do it, ID's are unique, and I don't want to say what ID's I have to use.

    very Last night I did get a version with JQuery and javascript working by itself, I thought that the DOM or my variable would persist but it does not, so I was effectively latching on to the wrong control hence the problem.

    Without the mouse over/out stuff, if you have a better solution than mouse over/out advice don't have ago, I'm normally a windows developer as well as a unity developer etc and other things.

    So web development I do for myself so it's bound to be a little unclean until I learn, I used Flex box for easier use later on.


    Thanks for you help!!

  6. #6
    Administrator VIPStephan's Avatar
    Join Date
    Jan 2006
    Location
    Halle (Saale), Germany
    Posts
    10,876
    Thanks
    6
    Thanked 1,299 Times in 1,269 Posts
    deathshadow, having a bad day again? Be a little more constructive, please, and don’t scare away new users (or any legitimate user, for that matter).

  7. #7
    Senior Coder deathshadow's Avatar
    Join Date
    Feb 2016
    Location
    Keene, NH
    Posts
    2,374
    Thanks
    2
    Thanked 338 Times in 328 Posts
    ... and I'm just disturbed that such a simple list of what's "wrong" is now somehow "rude". Hate to see how he'd have reacted had I ACTUALLY meant to be rude.

    Though if you are patterning after the bloated train wrecks of how NOT to build a website that are jQuery and Materialize, that would explain a LOT of my distaste for it and my thinking you are using ten times the code neccessary to do what you describe!

    Oh and a faster/cleaner way than playing with all the opacity values to hide it without breaking it (since IE treats display:none or visibility:hidden as if it were type="hidden") is to just do position:absolute; left:-999em;. You an then leave it intact.

    ... and the reason I brought up labels? If you were using <label> with a for attribute, you wouldn't need to trap onclick. Likewise you don't need to trap mouseover/mouseout, we have :hover for that, and if the label were sibling to the input, you can trap :focus on the input as well.

    A good portion of what you're using JavaScript to do can be done WITHOUT THE JavaScript! Never use JS to do HTML and CSS' job!

    Realistically there is little legitimate reason for what you have to vary significantly from:

    Code:
    <fieldset class="fileSet">
    	<div>
    		<label for="fileField1"><span>File</span></label>
    		<input type="file" id="fileField1" name="file[]">
    	</div><div>
    		<label for="fileField2"><span>File</span></label>
    		<input type="file" id="fileField2" name="file[]">
    	</div>
    </fieldset>
    The hover state for the cursor? that's CSS' job. Gimme a few minutes and I'll toss together a working example.
    I would rather have questions that can't be answered, than answers that can't be questioned.
    http://www.cutcodedown.com

  8. #8
    Senior Coder deathshadow's Avatar
    Join Date
    Feb 2016
    Location
    Keene, NH
    Posts
    2,374
    Thanks
    2
    Thanked 338 Times in 328 Posts
    Ok, big thing we want to do first is make sure there's a scripting off / disabled / blocked fallback. ALL GOOD SCRIPTING should be enhancing existing functionality, not supplanting it. To that end what we'll do is style the form to 'fit to width' using a legacy (non-flex) method of placing the labels and inputs to fill the parent container.

    Code:
    .fileSet {
    	padding-top:1em;
    	line-height:1.2em;
    }
    
    .fileSet div {
    	overflow:hidden; /* wrap floats and margins */
    	zoom:1; /* trip haslayout, wrap floats and margins legacy IE */
    	padding:0 1em 1.5em 5.5em;
    }
    
    .fileSet label:hover {
    	cursor:pointer;
    	cursor:hand; /* legacy IE */
    }
    
    .fileSet label span {
    	float:left;
    	width:4em;
    	margin-left:-4.5em;
    	padding:0.5em 0;
    	text-align:center;
    	background:#FF0;
    	color:#000;
    	-webkit-border-radius:0.5em;
    	border-radius:0.5em;
    }
    
    .fileSet input {
    	margin:0.5em -1em 0 0;
    	width:100%;
    	-webkit-box-sizing:padding-box;
    	-moz-box-sizing:padding-box;
    	-ms-box-sizing:padding-box;
    	box-sizing:padding-box;
    }
    This even sets up the hover state for the label, so we don't have to trap that event in the JavaScript!

    The method I use for placing the span inside the label is the 'negative margin column' technique. Whilst not as dynamic as flex, it's nice as it is compatible back to IE 5.x if need be. you just adjust the width, negative margin, and fieldset padding to adjust it.

    Side note, this assumes a reset is in place nulling margins/paddings, as well as border on fieldset.

    To show the text flat the SCRIPT should be adding a class to the fieldset to say "this is scripted" so further style can be applied. It would then also add a DIV inside the fieldset to show our filename however you want to style it. We then just aPo the input off-screen.

    Code:
    .fileSetScripted input {
    	position:absolute;
    	left:-999em;
    	width:5em;
    }
    
    .fileSetScripted label div {
    	min-height:1.2em;
    	padding:0.5em;
    	word-wrap:break-word;
    	border-bottom:2px solid #0C0;
    }
    The scripting... well, lemme throw it up as a live demo rather than trying to paste all the code in here:

    Index of /for_others/piggybank1974/ - CutCodeDown

    Follow along with:

    http://www.cutcodedown.com/for_other...styledFiles.js

    I start out with a self-instancing function that is passed window and document as "w" and "d". This way I'm not typing "document." five billion times over. Cute trick, actually speeds up execution as it moves it into the local namespace. Google uses it, good enough for them, good enough for me. This also means all our code is restricted in scope so it's highly unlikely other scripts on the page will interfere.

    IE8/earlier can't do getElementsByClassName, doesn't report onchange properly, doesn't give us input.files... it's just not worth trying to polyfill, so just give them the traditional normal input type="file" and focus on modern browsers for that. To that end if the browser being used can't do getElementsByClassName, just skip it like a kid in the '90's.

    I tossed in some handy helper functions. These are gutted down from my own elementals.js library just for a bit of node walking and control. NodeAdd/NodeAddTag/nodeFlush in particular are useful since it lets us add/remove content on the DOM instead of pissing the bed using innerHTML. If you use innerHTML or jQuery's idiotic workalike to put content into the page, you're triggering the parsing engine for the whole document. That takes WAY more time and battery than anything our JavaScript does on its own, can screw up values you set from the scripting, and in general is why 99% of the time you see innerHTML, someone is doing something wrong! About the only time innerHTML or anything that remotely looks like markup in a string should be considered acceptable practice is when what it is being applied to is not a live DOM element.

    The fileUpdate function is passed the input we want to process. During initialization I attach a "data_filename" attribute to the input that points at the DIV we add to the span, that's where the text gets plugged in. HTML 5's data- attributes are cute, but problematic in IE10/earlier and don't like having DOM nodes assigend to them. Switching to an underscore is simple, lets us assign any value we want, and is highly unlikely to risk a namespace collision.

    In any case first we flush that DIV's content, deleting all child nodes. This is functionally similar to e.innerHTML = ''; except that again we don't trip the parser meaning lower battery use, faster rendering, etc, etc.

    If the input has the files attribute we can assume a modern browser and just parse list all the files. I loop files instead of assuming [0] should there be no values. If there are values we use nodeAdd to put them on using the DOM. If it's not the first value we add a line-break first so each separate file is on its own line. (assuming it doesn't wordwrap). I would CONSIDER expanding this further depending on how you want to present multiple files. (in the test note the first input is set to 'multiple')

    IE9/earlier doesn't have 'HTMLInputElement.files' or the 'multiple' attribute, so we parse out just the filename and make that our content instead.

    "fileChange" is just an event wrapper. I made it a static function so that when we assign it using addEventListener we aren't making endless multiple copies like an anonymous function would. REmember if you are assigning it only once, use an anonymous. If you are assigning it more than once, make it a full static function!

    fileChange is separate form fileUpdate as we will also want to call update during pageload should our input already have values assigned to them, such as during a soft-refresh in Firefox or Chrome. (aka F5 instead of ctrl-F5)

    I then get all the fieldsets that have the class fileset, loop through them (if any) getting all inputs inside them. We figure out the label using nodePrevious (best guess, don't screw with the source order!) and put a DIV into it, assigning that div to our custom input.data_filenameSpan attribute as mentioned earlier. Hook the onchange, update should there be any existing value, and we're done.

    Gets the style out of the markup, lets CSS do CSS' job, keeps scripting only elements out of the markup, and works with multiple file results in modern browsers, uses the DOM like a good little doobie instead of the problematic (and should probably be deprecated) innerHTML, etc, etc.

    Might look like a hair more code, until you realize how big what you were doing would end up markup-wise if you had six of them on a page instead of just two. Your original sample was 3.63k with just two input and the raw scripting without a full document around it. This rewrite/demo 3.99k combined and that's with a reset, full HTML document, 6 inputs and proper "multiple" support -- WITH scripting off and legacy fallback to normal type="file" behavior.

    Hope that helps...

    -- edit -- I also added a .txt of the HTML to the directory in case you don't know how to view-source.
    Last edited by deathshadow; 08-13-2017 at 05:52 AM.
    I would rather have questions that can't be answered, than answers that can't be questioned.
    http://www.cutcodedown.com


 

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •